package eu.tsp.isensors.test.communication;

import java.io.IOException;
import java.util.Calendar;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.ServiceProperty;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Property;

import java.io.BufferedReader;
import java.io.BufferedInputStream;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;


import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.FileItem;
import java.util.List;
import java.util.Iterator;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;
import java.text.SimpleDateFormat;

//XML
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;

import org.w3c.dom.Document;
import org.w3c.dom.Element;


@Component
@Provides
public class Node extends RestServlet{

   @ServiceProperty
   private String alias; // In the instance configuration
   
   @Property(mandatory=true)
   String nodeID;
   
   @Requires
   public eu.tsp.isensors.services.storage.Put m_put; // Service Dependency
   
   @Requires
   public eu.tsp.isensors.services.storage.Get m_get; // Service Dependency
   
   @Requires
   public eu.tsp.isensors.services.storage.Delete m_delete; // Service Dependency
   
   @Requires
   public eu.tsp.isensors.services.alert.gen.ReceivedData receiv2AlertGen; // Service Dependency
  
   /**
    * GET an entry. The base class will populate the "entryId" attribute before calling invoke.
    * We told it to do so below, when we defined entryIdentifier.
    */
   RequestHandler entryGetHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           try {
               // The base class has parsed the URI and populated the request with
               // the "entryId" attribute
               String entryId = (String)request.getAttribute("entryId");
               //Pour noter la différence entre request.getRequestURI() VS request.getServletPath()
	       System.out.println(">> entryGetHandler "+entryId+"*"+ request.getRequestURI() + "*" + request.getServletPath()+"*");
               String forward = "/WEB-INF/entry.jsp";
               request.setAttribute("entryHTML", getEntryHTML(entryId));
               request.setAttribute("entryTitle", getEntryTitle(entryId));
              
               request.getRequestDispatcher(forward).forward(request, response);
           } catch (Exception e) {
               response.sendError(404);
           }
       }         
   };
  
   
   /**
    * POST a new entry to the collection URI
    */
   RequestHandler collectionPostHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           try {
               String entryId = saveEntry(request, response);  
              
               response.setHeader("Location", buildEntryUri(entryId));
               response.setStatus(201);
               //write out some HTML or maybe the entry itself.
               String forward = "/WEB-INF/entry.jsp";
               request.setAttribute("entryHTML", getEntryHTML(entryId));
               request.setAttribute("entryTitle", getEntryTitle(entryId));
              request.getRequestDispatcher(forward).forward(request, response);
           } catch (Exception e) {
               response.sendError(404);
           }
       }         
   };
   
   
  
   //Stubbing these in...
   RequestHandler entryPutHandler = null;
   RequestHandler entryDeleteHandler = null;
   RequestHandler collectionGetHandler = null;

   //
   // One ResourceIdentifier per URI pattern. 
   // Each one tells us how to parse the pattern into attributes, and handlers
   // for HTTP methods on the resources it identifies.
   //
   ResourceIdentifier entryIdentifier = new ResourceIdentifier(       
           "^/(\\d+)$",                // URI pattern
           new String[] {"entryId"},   // match pattern and insert named request attributes
           entryGetHandler,            // GET handler for entry URIs
           null,                       // no POST handler for entries
           entryPutHandler,            // PUT an entry
           entryDeleteHandler);        // DELETE an entry
                                
   
    /**
    * GET information about sensorID
    */
   RequestHandler sensorIdentifierGetHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       	   System.out.println(" > sensorIdentifierGetHandler");
           try {
               String servletPath = request.getServletPath();
               
               
               String  sensorID = (String)request.getAttribute("sensorID");
               String  id = (String)request.getAttribute("id");
               
               byte[] bb = m_get.get(id);
               
               System.out.println(" > sensorIdentifierGetHandler : "+ servletPath + " nodeID:" + nodeID + " sensorID:" + sensorID + " id:" + id);
               ServletOutputStream out = response.getOutputStream();
               out.println("This is a snippest information about node : "+nodeID + "\n"+servletPath + " nodeID:" + nodeID + " sensorID:" + sensorID + " id:" + id);
               out.println(new String(bb));
               out.close();
           } catch (Exception e) {
               response.sendError(404);
           }
       }         
   };
   
   RequestHandler sensorIdentifierPutHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       	   System.out.println(" > sensorIdentifierPutHandler");
           try {
           	Calendar cal = Calendar.getInstance();
               String servletPath = request.getServletPath();
               //String fileXml = m_get.get_as_string("/db/examples.xml");
               //byte[] bb = m_get.get("/db/examples.xml");
               String  sensorID = (String)request.getAttribute("sensorID");
               
               InputStream input = request.getInputStream();
               byte[] bytes = IOUtils.toByteArray(input);
               
               String data_uid = "", data_name = nodeID+"-"+sensorID+"-"+cal.getTimeInMillis();
               
               data_uid = m_put.put("/db/nodes/" + nodeID + "/sensors/" + sensorID, request.getContentType() , bytes, data_name);
               
               System.out.println(" > sensorIdentifierPutHandler : "+ servletPath + " nodeID:" + nodeID + " sensorID:" + sensorID );
               
               receiv2AlertGen.thisIsReID(nodeID, servletPath, data_uid);
               
               ServletOutputStream out = response.getOutputStream();
               out.println(" > sensorIdentifierPutHandler : "+nodeID + 
               	       "\n"+servletPath + " nodeID:" + nodeID + " sensorID:" + sensorID + "request.getContentType():"+ 
               	       request.getContentType() + "data_name:" + data_name + "data uid:" + data_uid );
               out.println(new String(bytes));
               //out.println(fileXml);
               out.close();
           }
               catch (IOException e) {}
           catch (Exception e) {
               response.sendError(404);
           }
       }         
   };
   
   
   ResourceIdentifier sensorIdentifierGet = new ResourceIdentifier(       
           "^/sensors/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$",	// URI pattern 
		   new String[] {"sensorID", "id"},   // match pattern and insert named request attributes
		   sensorIdentifierGetHandler            // GET handler for entry URIs
		   );
   ResourceIdentifier sensorIdentifierPut = new ResourceIdentifier(       
           "^/sensors/([a-zA-Z0-9_-]+)$",                // URI pattern
           new String[] {"sensorID"},   // match pattern and insert named request attributes
           null,            // GET handler for entry URIs
           null,                       // no POST handler for entries
           sensorIdentifierPutHandler,            // PUT an entry
           null);        // DELETE an entry
  


/* ***********************************************************************************
    *****************   E A S Y   A P I   **************************************************
    ***********************************************************************************
*/

/**
 * URL : isensors/nodes/{nodeid}/
 *	POST :	ERROR
 *	GET  :	Node description OR {id}
 *	PUT  :	Update/create node description
 *	DELETE	ERROR
 */

   /**
    * GET information about nodeID
    *
    * ToDo: retourne que le node id mais pas la desc.
    */
   RequestHandler nodeGetHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       	    try {
               //String nodeId = request.getServletPath();
               //String nodeDescription = m_get.get_as_string("/db/nodes/" + nodeID + "/desc/"+nodeID+"-desc");
               byte[] nodeDescription = m_get.get("/db/nodes/" + nodeID + "/desc/"+nodeID+"-desc");
               String tNodeDescription = new String (nodeDescription);
               //byte[] bb = m_get.get("/db/examples.xml");
               //System.out.println("GET Res: \n FILEXML"+fileXml+"\n BYTES"+new String(bb));
               //System.out.println("uri : /db/nodes/" + nodeID + "/desc/"+nodeID+"-desc"+ "\n nodeDescription **\n"+nodeDescription+"\n Fin nodeDescription");
               ServletOutputStream out = response.getOutputStream();
               if(tNodeDescription.contains("<h2>HTTP ERROR: 404</h2>"))
               	       out.println("Node : "+nodeID +"\n");
               else 
               	       out.println(tNodeDescription);
               out.close();
           } catch (Exception e) {
               response.sendError(404);
           }
       }         
   };
   /**
     *  Put node desc. 
     *
     *  Get description file and return an identifier
     *
     */
      RequestHandler nodePutDescriptionHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       	   System.out.println("nodePutDescriptionHandler");
           try {
               //Calendar cal = Calendar.getInstance();
               String servletPath = request.getServletPath();
               //String fileXml = m_get.get_as_string("/db/examples.xml");
               //byte[] bb = m_get.get("/db/examples.xml");
               //String  sensorID = (String)request.getAttribute("sensorID");
               InputStream input = request.getInputStream();
               byte[] bytes = IOUtils.toByteArray(input);
               String desc = new String(bytes);
               int headerEnd = desc.indexOf("Content-Type: ");
	       headerEnd = desc.indexOf("<", headerEnd);
	       System.out.println("headerEnd :"+headerEnd);
	       System.out.println("desc :"+desc);
	       int footerStart = desc.lastIndexOf("------");
	       System.out.println("footerStart :"+footerStart);
	       desc = desc.substring(headerEnd, footerStart);
	       System.out.println("ok3");
               
               String data_uid = "", 
               data_name = nodeID+"-desc";//+cal.getTimeInMillis();
               
               data_uid = m_put.put("/db/nodes/" + nodeID + "/desc" , request.getContentType() , desc.getBytes(), data_name);
               
               //System.out.println(" > nodePutDescriptionHandler : "+ servletPath + " nodeID:" + nodeID);
               
               //receiv2AlertGen.thisIsReID(nodeID, servletPath, data_uid);
               
               ServletOutputStream out = response.getOutputStream();
               //out.println(" > nodePutDescriptionHandler : "+nodeID +  "\n"+servletPath + " nodeID:" + nodeID + "request.getContentType():"+ request.getContentType() + "data_name:" + data_name + "data uid:" + data_uid );
               //out.println(new String(bytes));
               //out.println(fileXml);
               out.println(data_uid);
               out.println("Received Data :");
               out.println(new String(bytes));

               out.close();
           	}
               catch (IOException e) {e.printStackTrace();}
               catch (Exception e) {
               		e.printStackTrace();
               		response.sendError(404);
           	}
       }         
   };
   ResourceIdentifier nodeResource = new ResourceIdentifier(       
           "^/$",                // URI pattern
           new String[] {},   // match pattern and insert named request attributes
           nodeGetHandler,            // GET handler for entry URIs
           null,                       // no POST handler for entries
           nodePutDescriptionHandler,            // PUT an entry
           null);        // DELETE an entry
   
/**
 * URL : isensors/nodes/{nodeid}/data
 *	POST :	Add new data (message, packet, …)
 *	GET  :	Last sent data
 *	PUT  :	ERROR
 *	DELETE	ERROR
 */
 
  String lastSentData ="";
 
 /**
    *  POST : add new data
    *
    */
    RequestHandler postNodeDataHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException,  FileUploadException{
       	       if (ServletFileUpload.isMultipartContent(request)){ //Checking If an HTTP Request is Encoded in Multipart Format
       	       	       ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
       	       	       try {
       	       	       	       List fileItemsList = servletFileUpload.parseRequest(request);
       	       	       	       /* Process file items... */
       	       	       	       Iterator it = fileItemsList.iterator();
       	       	       	       while (it.hasNext()){
       	       	       	       	       FileItem fileItem = (FileItem)it.next();
       	       	       	       	       if (fileItem.isFormField()){
       	       	       	       	       	       /* The file item contains a simple name-value pair of a form field */
       	       	       	       	       	       String name = fileItem.getFieldName();
       	       	       	       	       	       String value = fileItem.getString();
       	       	       	       	       }
       	       	       	       	       else{
       	       	       	       	       	       /* The file item contains an uploaded file */
       	       	       	       	       	       /* Get the name attribute value of the <input type="file"> element. */
       	       	       	       	       	       String fieldName = fileItem.getFieldName();

       	       	       	       	       	       /* Get the size of the uploaded file in bytes. */
       	       	       	       	       	       long fileSize = fileItem.getSize();

       	       	       	       	       	       /* Get the name of the uploaded file at the client-side. Some browsers such as IE 6 include the whole path here (e.g. e:\files\myFile.txt), 
       	       	       	       	       	       	   so you may need to extract the file name from the path. This information is provided by the client browser, which means you should be 
       	       	       	       	       	       	   cautious since it may be a wrong value provided by a malicious user. 
       	       	       	       	       	          */
       	       	       	       	       	       String fileName = fileItem.getName();
       	       	       	       	       	       
       	       	       	       	       	       /* Get the content type (MIME type) of the uploaded file. This information is provided by the client browser, which means you should be 
       	       	       	       	       	       	   cautious since it may be a wrong value provided by a malicious user. 
       	       	       	       	       	          */
       	       	       	       	       	       String contentType = fileItem.getContentType();
       	       	       	       	       	       
       	       	       	       	       	       /* Get File bytes */
       	       	       	       	       	       byte[] fileData = fileItem.get();
       	       	       	       	       	       // or use this method if you expect larger files 
       	       	       	       	       	       // InputStream fileStream = fileItem.getInputStream();
       	       	       	       	       	       // byte[] bytes = IOUtils.toByteArray(input);
       	       	       	       	       	       
       	       	       	       	       	       /* Put service call */
       	       	       	       	       	       Calendar cal = Calendar.getInstance();
       	       	       	       	       	       String data_uid = "", 
       	       	       	       	       	       		 data_name = nodeID+"-data-"+cal.getTimeInMillis();
               
       	       	       	       	       	       SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
       	       	       	       	       	       
       	       	       	       	       	       data_uid = m_put.put("/db/nodes/" + nodeID + "/data/" + sdf.format(cal.getTime()) , fileItem.getContentType() , fileData, data_name);
       	       	       	       	       	       
       	       	       	       	       	       /* Debug */
       	       	       	       	       	       System.out.println(" > postNodeDataHandler : "+ " nodeID:" + nodeID + " data_uid:" + data_uid);
       	       	       	       	       	       
       	       	       	       	       	       /* Save last data received */
       	       	       	       	       	       lastSentData = data_uid;
       	       	       	       	       	       
       	       	       	       	       	       receiv2AlertGen.thisIsReID(nodeID, request.getRequestURI(), data_uid);
       	       	       	       	       	       
       	       	       	       	       	       /* Response */
       	       	       	       	       	       ServletOutputStream out = response.getOutputStream();
       	       	       	       	       	       out.println(data_uid);
       	       	       	       	       	       
       	       	       	       	       	       out.close();
       	       	       	       	       }
       	       	       	       }
       	       	       }
       	       	       catch (SizeLimitExceededException ex) {
       	       	       	       /* The size of the HTTP request body exceeds the limit */
       	       	       }
       	       }
       	       else{
       	       	       System.out.println(" >  is NOT MultipartContent... \n");
       	       }
       }
    };
    
    RequestHandler getLastNodeDataHandler = new RequestHandler(){

    	    public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	    	    if(! lastSentData.equals("")){
    	    	    	    byte[] bb = m_get.get(lastSentData);
    	    	    	    ServletOutputStream output = response.getOutputStream();
    	    	    	    output.write(bb);
    	    	    	    output.close();
    	    	    }
    	    }
    };
    
    ResourceIdentifier nodeDataResource = new ResourceIdentifier(       
           "^/data$",                // URI pattern
           new String[] {},   // match pattern and insert named request attributes
           getLastNodeDataHandler,            // GET handler for entry URIs
           postNodeDataHandler,                       // no POST handler for entries
           null,            // PUT an entry
           null);        // DELETE an entry
 
/**
 * URL : isensors/nodes/{nodeid}/data/{data_id}
 *	POST :	ERROR
 *	GET  :	Get the data
 *	PUT  :	ERROR
 *	DELETE	ERROR
 */
    RequestHandler getNodeDataIDHandler = new RequestHandler(){

    	    public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	    	    String data_id = (String)request.getAttribute("data_id");
    	    	    byte[] bb = m_get.get(data_id);
    	    	    ServletOutputStream output = response.getOutputStream();
    	    	    output.write(bb);
    	    	    output.close();
    	    }
    };
    
    ResourceIdentifier nodeDataIDResource = new ResourceIdentifier(       
           "^/data/([a-zA-Z0-9_-]+)$",                // URI pattern
           new String[] {"data_id"},   // match pattern and insert named request attributes
           getNodeDataIDHandler,            // GET handler for entry URIs
           null,                       // no POST handler for entries
           null,            // PUT an entry
           null);        // DELETE an entry

/**
 * URL : isensors/nodes/{nodeid}/config
 *	POST :	Create new configuration file at the nodeId local repository (form 2 metalist)
 *	GET  :	ERROR
 *	PUT  :	ERROR
 *	DELETE	ERROR
 */
    RequestHandler postConfigparamsHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException,  FileUploadException{
       	       System.out.println(" >  postConfigparamsHandler ... \n");
       	       if (ServletFileUpload.isMultipartContent(request)){ //Checking If an HTTP Request is Encoded in Multipart Format
       	          	
       	       		String xml = form2Metalist(request);	       	       
       	       	       	//Enregistrement du fichier de configuration 
       	       	       	Calendar cal = Calendar.getInstance();
       	       	       	String data_uid = "", 
       	       	       		  config_name = nodeID+"-config-"+cal.getTimeInMillis();
       	       	       	       	       	       
       	       	       	data_uid = m_put.put("/db/nodes/" + nodeID + "/config/" , "application/xml" , xml.getBytes(), config_name);
       	       	       	       
       	       	       	out(data_uid, response);
       	       }
       	       else{
       	       	       System.out.println(" >  is NOT MultipartContent... \n");
       	       }
       }
    };
    // Method to save form posted in a matalist file 
    private String form2Metalist(HttpServletRequest request)throws IOException, FileUploadException{
    	    ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
       	    try {
       	    	    /* Get items from request */
       	       	    List fileItemsList = servletFileUpload.parseRequest(request);
       	       	       	       
       	       	    /* Initialise xml file where to store them */
       	       	    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
       	       	    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
       	       	       	       
       	       	    // root elements
       	       	    Document doc = docBuilder.newDocument();
       	       	    Element rootElement = doc.createElement("metalist");
       	       	    doc.appendChild(rootElement);
		
       	       	     /* Process file items... */
       	       	     Iterator it = fileItemsList.iterator();
       	       	     while (it.hasNext()){
       	       	     	     FileItem fileItem = (FileItem)it.next();
       	       	       	     if (fileItem.isFormField()){
       	       	       	     	     /* The file item contains a simple name-value pair of a form field */
       	       	       	       	     Element metadata = doc.createElement("metadata");
       	       	       	       	     metadata.setAttribute("attribute", fileItem.getFieldName());
       	       	       	       	     metadata.appendChild(doc.createTextNode(fileItem.getString()));
       	       	       	       	     rootElement.appendChild(metadata);
       	       	       	       	     //String name = fileItem.getFieldName();
       	       	       	       	     //String value = fileItem.getString();
       	       	       	      }
       	       	       	      else{
       	       	       	      }
       	       	     }
       	       	       	       
       	       	      String xml = xml2String(doc);
       	       	       	       
       	       	      return xml;
       	       	       	       
       	       }
       	       catch (SizeLimitExceededException ex) {
       	       	        /* The size of the HTTP request body exceeds the limit */
       	       	        ex.printStackTrace();
       	       } catch (ParserConfigurationException pce) {
       	       	       	pce.printStackTrace(); 
       	       } catch (TransformerException tfe) {
       		tfe.printStackTrace();
       	       }
       	       return "";
    }
    
    //Method to convert XML to String
    private String xml2String(Document doc) throws IOException, TransformerException{
    	    TransformerFactory factory = TransformerFactory.newInstance();
       	    Transformer transformer = factory.newTransformer();
       	    StringWriter writer = new StringWriter();
       	    StreamResult result = new StreamResult(writer);
       	    DOMSource source = new DOMSource(doc);
       	    transformer.transform(source, result);
       	    writer.close();
       	    String xml = writer.toString();
       	    System.out.println(xml);
       	    return xml;   	
    }
    
    //curl --form "name=I am Daniel" http://localhost:8181/isensors/nodes/333-214/config
    //curl --form upload=@localfilename --form press=OK [URL]
    ResourceIdentifier createNewConfigResource = new ResourceIdentifier(       
           "^/config$",                // URI pattern
           new String[] {},   // match pattern and insert named request attributes
           null,            // GET handler for entry URIs
           postConfigparamsHandler,                       // POST handler
           null,            // PUT an entry
           null);        // DELETE an entry


    
/**
 * URL : isensors/nodes/{nodeid}/config/{config_id}
 *	POST :	Create/update configuration file  with {config-id} (form 2 metalist)
 *	GET  :	GET the configuration file {config-id}
 *	PUT  :	Update the configuration file   {config-id} by uploading a new file
 *	DELETE	Delete the configuration file   {config-id}
 */ 
    RequestHandler postConfigIDparamsHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException,  FileUploadException{
       	       if (ServletFileUpload.isMultipartContent(request)){ //Checking If an HTTP Request is Encoded in Multipart Format
       	          	
       	       		String xml = form2Metalist(request);	       	       
       	       	       	//Enregistrement du fichier de configuration 
       	       	       	String data_uid = "", 
       	       	       		  config_id = (String)request.getAttribute("config_id");;
       	       	       	       	       	       
       	       	       	data_uid = m_put.put(config_id , "application/xml" , xml.getBytes());
       	       	       	       
       	       	       	out(data_uid, response);
       	       }
       	       else{
       	       	       System.out.println(" >  is NOT MultipartContent... \n");
       	       }
       }
    };
    
    RequestHandler getConfigIDFileHandler = new RequestHandler(){
       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
       	       String config_id = (String)request.getAttribute("config_id");
    	    	    byte[] bb = m_get.get(config_id);
    	    	    out(bb, response);
       }
    };
    
    RequestHandler putConfigIDFileHandler = new RequestHandler(){
       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           try {
               InputStream input = request.getInputStream();
               byte[] bytes = IOUtils.toByteArray(input);
               
               String data_uid = "", 
               config_id = (String)request.getAttribute("config_id");
               
               data_uid = m_put.put(config_id , request.getContentType() , bytes);
               
               out(data_uid, response);
           }
               catch (IOException e) {}
               		catch (Exception e) {
               response.sendError(404);
           }
       }         
   };
   
   RequestHandler deleteConfigIDFileHandler = new RequestHandler(){
       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
       	       String config_id = (String)request.getAttribute("config_id");
    	    	    byte[] bb = m_delete.delete(config_id);
    	    	    out(bb, response);
       }
    };
    
    ResourceIdentifier updateConfigResource = new ResourceIdentifier(       
           "^/config/([a-zA-Z0-9_-]+)$",                // URI pattern
           new String[] {"config_id"},   // match pattern and insert named request attributes
           getConfigIDFileHandler,            // GET handler for entry URIs
           postConfigIDparamsHandler,                       // POST handler
           putConfigIDFileHandler,            // PUT an entry
           deleteConfigIDFileHandler);        // DELETE an entry
    
 /**
 * URL : isensors/nodes/{nodeid}/script
 *	POST :	Create new script file at the nodeId local repository using an uploaded file
 *	GET  :	ERROR
 *	PUT  :	ERROR
 *	DELETE	ERROR
 */
   RequestHandler postCreateNewScriptHandler = new RequestHandler(){

       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException,  FileUploadException{
       	       if (ServletFileUpload.isMultipartContent(request)){ //Checking If an HTTP Request is Encoded in Multipart Format
       	          	
       	       	       ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
       	       	       try {
       	       	       	       List fileItemsList = servletFileUpload.parseRequest(request);
       	       	       	       /* Process file items... */
       	       	       	       Iterator it = fileItemsList.iterator();
       	       	       	       while (it.hasNext()){
       	       	       	       	       FileItem fileItem = (FileItem)it.next();
       	       	       	       	       if (fileItem.isFormField()){
       	       	       	       	       	       /* The file item contains a simple name-value pair of a form field */
       	       	       	       	       	       String name = fileItem.getFieldName();
       	       	       	       	       	       String value = fileItem.getString();
       	       	       	       	       }
       	       	       	       	       else{
       	       	       	       	       	       String fieldName = fileItem.getFieldName();
       	       	       	       	       	       
       	       	       	       	       	       /* Get the size of the uploaded file in bytes. */
       	       	       	       	       	       long fileSize = fileItem.getSize();

       	       	       	       	       	       String fileName = fileItem.getName();
       	       	       	       	       	       
       	       	       	       	       	       String contentType = fileItem.getContentType();
       	       	       	       	       	       
       	       	       	       	       	       /* Get File bytes */
       	       	       	       	       	       byte[] fileData = fileItem.get();
       	       	       	       	       	       
       	       	       	       	       	       /* DEBUG */
       	       	       	       	       	       System.out.println("fieldName: "+fieldName+"-fileName: "+fileName+"contentType: "+contentType+"*");
       	       	       	       	       	       
       	       	       	       	       	       /* Put service call */
       	       	       	       	       	       Calendar cal = Calendar.getInstance();
       	       	       	       	       	       String data_uid = "", 
       	       	       	       	       	       		data_name = fileName;//nodeID+"-script-"+cal.getTimeInMillis();
       	       	       	       	       	       
       	       	       	       	       	       data_uid = m_put.put("/db/nodes/" + nodeID + "/script/" , "application/xquery" , fileData, data_name);
       	       	       	       	       	       
       	       	       	       	       	       /* Response */
       	       	       	       	       	       out(data_uid.replaceAll("_", "/"), response);
       	       	       	       	       }
       	       	       	       }
       	       	       }
       	       	       catch (SizeLimitExceededException ex) {
       	       	       	       /* The size of the HTTP request body exceeds the limit */
       	       	       }
       	       }
       	       else{
       	       	       System.out.println(" >  is NOT MultipartContent... \n");
       	       }
       }
    };
    
    ResourceIdentifier createNewScriptResource = new ResourceIdentifier(       
           "^/script$",                // URI pattern
           new String[] {},   // match pattern and insert named request attributes
           null,            // GET handler for entry URIs
           postCreateNewScriptHandler,                       // POST handler
           null,            // PUT an entry
           null);        // DELETE an entry
    
 /**
 * URL : isensors/nodes/{nodeid}/script/{script-id}
 *	POST :	ERROR
 *	GET  :	GET the script file {script-id}
 *	PUT  :	Update the script file   {script-id} by uploading a new file
 *	DELETE	Delete the script file   {config-id}
 */
   RequestHandler getScriptIDFileHandler = new RequestHandler(){
       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
       	       String script_id = (String)request.getAttribute("script_id");
    	    	    byte[] bb = m_get.get(script_id);
    	    	    out(bb, response);
       }
    };
    RequestHandler putScriptIDFileHandler = new RequestHandler(){
       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           try {
               InputStream input = request.getInputStream();
               byte[] bytes = IOUtils.toByteArray(input);
               
               String data_uid = "", 
               script_id = (String)request.getAttribute("script_id");
               
               data_uid = m_put.put(script_id , request.getContentType() , bytes);
               
               out(data_uid, response);
           }
               catch (IOException e) {}
               		catch (Exception e) {
               response.sendError(404);
           }
       }         
   };
   
   RequestHandler deleteScriptIDFileHandler = new RequestHandler(){
       public void invoke(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
       	       String script_id = (String)request.getAttribute("script_id");
    	    	    byte[] bb = m_delete.delete(script_id);
    	    	    out(bb, response);
       }
    };
    
    ResourceIdentifier updateScriptResource = new ResourceIdentifier(       
           "^/script/([a-zA-Z0-9_-]+)$",                // URI pattern
           new String[] {"script_id"},   // match pattern and insert named request attributes
           getScriptIDFileHandler,            // GET handler for entry URIs
           null,                       // POST handler
           putScriptIDFileHandler,            // PUT an entry
           deleteScriptIDFileHandler);        // DELETE an entry
   @Override
   /**
    * Here's how we tell our base class how to map URIs to handlers:
    */
   protected ResourceIdentifier[] resourceIdentifiers() {      
       return new ResourceIdentifier[]{entryIdentifier, sensorIdentifierGet, sensorIdentifierPut, createNewConfigResource, updateConfigResource, createNewScriptResource, updateScriptResource, nodeResource, nodeDataResource, nodeDataIDResource};
   }

   // these are just stubs... exercise for the reader.
   private String buildEntryUri(String entryId) {
       return null;
   }

   private String saveEntry(HttpServletRequest request,
           HttpServletResponse response) {
       return null;
   }

   private Object getEntryTitle(String entryId) {
       return null;
   }
   private Object getEntryHTML(String entryId) {
       return null;
   }
  
   private void out(byte[] bb, HttpServletResponse response) throws  IOException{
   	   ServletOutputStream output = response.getOutputStream();
    	   output.write(bb);
    	   output.close();
   }
   
   private void out(String bb, HttpServletResponse response) throws IOException{
   	   ServletOutputStream output = response.getOutputStream();
    	   output.println(bb);
    	   output.close();
   }
}
